/** @format */

import * as Router from 'koa-router';
import {config} from '../config';
import {sql} from '../mysql';
import * as path from 'path';
import * as fs from 'fs';
import {to, sha256, readFile, writeFile, formateTime} from '../utils';
import * as uuidv4 from 'uuid/v4';
interface IData {
  id: number;
  title: string;
  category: string;
  markdown: string;
  html: string;
  release_date: string;
  visits: number;
}

interface IRspData {
  [props: string]: any;
}

const {apiVersion} = config;

// 系统错误报文
const SYSTEM_ERROR_MGS = {
  msgCode: 1,
  msg: '系统错误，请稍后重试',
};

// 错误报文
const ERROR_MGS = (msg: string) => {
  return {
    msgCode: 1,
    msg,
  };
};

const urls = {
  adminAuth: '/admin',
  login: '/login',
  getConfig: '/admin/getConfig',
  postConfig: '/admin/postConfig',
  getUserList: '/admin/getUserList',
  postPwd: '/admin/postPwd',
  addUser: '/admin/addUser',
  deleteUser: '/admin/deleteUser',
  getArticleMarkdown: '/admin/getArticleMarkdown',
  uploadFile: '/admin/uploadFile',
  addBlog: '/admin/addBlog',
  getArticlesList: '/admin/getArticlesList',
  deleteArticle: '/admin/deleteArticle',
  getCategory: '/admin/getCategory',
};

// 拼接 api 版本
Object.keys(urls).forEach((item: string) => {
  (urls as any)[item] = apiVersion + (urls as any)[item];
});

const router = new Router();

// 统一验证登录
router.use(urls.adminAuth, async (ctx, next) => {
  const authToken = ctx.request.headers.authorization && ctx.request.headers.authorization.replace('Bearer ', '');
  // 未登录
  if (!authToken) {
    return (ctx.body = {
      msgCode: -1,
    });
  }

  const [err, existData]: any = await to(
    sql(`SELECT user FROM user WHERE token = '${sha256(config.cryptoSolt, authToken)}'`),
  );

  if (err) {
    return (ctx.body = SYSTEM_ERROR_MGS);
  }

  // 未登录
  if (!existData.results.length) {
    return (ctx.body = {
      msgCode: -1,
    });
  }

  ctx.state.user = existData.results[0]['user'];

  await next();
});

// 登录
router.post(urls.login, async ctx => {
  const reqUser = ctx.request.body.user;
  const reqPwd = ctx.request.body.pwd;
  if (!(reqUser && reqPwd)) {
    return (ctx.body = ERROR_MGS('用户名或密码不能为空'));
  }

  if (reqPwd.length < 6) {
    return (ctx.body = ERROR_MGS('密码长度至少为6位'));
  }

  const pwd = sha256(config.cryptoSolt, reqPwd);
  const [err, existData]: any = await to(
    sql(`SELECT * FROM user WHERE user = '${reqUser}' AND pwd = '${pwd}'
    `),
  );
  if (err) {
    return (ctx.body = SYSTEM_ERROR_MGS);
  }
  if (existData.results.length) {
    const token = uuidv4();
    const [updateErr]: any = await to(
      sql(`UPDATE user SET token = '${sha256(config.cryptoSolt, token)}' WHERE user = '${reqUser}' AND pwd = '${pwd}'
    `),
    );

    if (updateErr) {
      return (ctx.body = SYSTEM_ERROR_MGS);
    }
    ctx.body = {
      data: {
        token,
      },
    };
  } else {
    ctx.body = ERROR_MGS('用户名或密码错误');
  }
});

// 获取配置信息
router.get(urls.getConfig, async ctx => {
  const [errGetConfig, configData]: any = await to(readFile(path.resolve(`${__dirname}/../config/setting.json`)));

  if (errGetConfig) {
    return (ctx.body = SYSTEM_ERROR_MGS);
  }
  ctx.body = {
    data: {
      configData: ctx.query.mode === 'json' ? JSON.parse(configData) : configData,
    },
  };
});

// 更新配置信息
router.post(urls.postConfig, async ctx => {
  if (ctx.state.user !== 'admin') {
    return (ctx.body = ERROR_MGS('越权操作'));
  }
  const [postConfigErr]: any = await to(
    writeFile(path.resolve(`${__dirname}/../config/setting.json`), ctx.request.body.config),
  );

  if (postConfigErr) {
    return (ctx.body = SYSTEM_ERROR_MGS);
  }
  ctx.body = {
    data: {
      msg: '更新成功',
    },
  };
});

// 获取用户列表 （后台可以登录的用户）
router.get(urls.getUserList, async ctx => {
  const [errUserList, userList]: any = await to(sql(`SELECT id,user FROM user`));
  if (errUserList) {
    return (ctx.body = SYSTEM_ERROR_MGS);
  }

  ctx.body = {
    data: {
      userList: userList.results,
    },
  };
});

// 更新用户密码
router.post(urls.postPwd, async ctx => {
  if (ctx.state.user !== 'admin') {
    return (ctx.body = ERROR_MGS('越权操作'));
  }
  if (!ctx.request.body.newPwd || !ctx.request.body.user) {
    return (ctx.body = SYSTEM_ERROR_MGS);
  }
  const [postPwdErr, postPwdRsp]: any = await to(
    sql(
      `UPDATE user SET pwd = '${sha256(config.cryptoSolt, ctx.request.body.newPwd)}' WHERE user = '${
        ctx.request.body.user
      }'`,
    ),
  );
  if (postPwdErr || postPwdRsp.results.affectedRows === 0) {
    return (ctx.body = SYSTEM_ERROR_MGS);
  }
  ctx.body = {
    data: {
      msg: '更新成功',
    },
  };
});

// 删除用户
router.delete(urls.deleteUser, async ctx => {
  if (ctx.state.user !== 'admin') {
    return (ctx.body = ERROR_MGS('越权操作'));
  }

  if (ctx.request.query.user === 'admin') {
    return (ctx.body = ERROR_MGS('删除失败 admin账户不可删除'));
  }
  const [deleteUserErr, rsp]: any = await to(sql(`DELETE FROM user WHERE user = '${ctx.request.query.user}'`));

  if (deleteUserErr || rsp.results.affectedRows === 0) {
    return (ctx.body = SYSTEM_ERROR_MGS);
  }
  ctx.body = {
    data: {
      msg: '删除成功',
    },
  };
});

// 增加用户
router.post(urls.addUser, async ctx => {
  const reqUser = ctx.request.body.user;
  const reqPwd = ctx.request.body.pwd;
  if (!(reqUser && reqPwd)) {
    return (ctx.body = ERROR_MGS('用户名或密码不能为空'));
  }

  if (reqPwd.length < 6) {
    return (ctx.body = ERROR_MGS('密码长度至少为6位'));
  }
  if (ctx.state.user !== 'admin') {
    return (ctx.body = ERROR_MGS('越权操作'));
  }

  const [userExitErr, userExitRsp]: any = await await to(sql(`SELECT user FROM user WHERE user = '${reqUser}'`));

  if (userExitErr) {
    return (ctx.body = SYSTEM_ERROR_MGS);
  }

  if (userExitRsp.results.length) {
    return (ctx.body = ERROR_MGS('该用户名已存在 请重试'));
  }

  const pwd = sha256(config.cryptoSolt, reqPwd);
  const [addUserErr, addUserRsp]: any = await to(sql(`INSERT INTO user (user,pwd) VALUES ('${reqUser}','${pwd}')`));

  if (addUserErr || !addUserRsp.results.affectedRows) {
    return (ctx.body = SYSTEM_ERROR_MGS);
  }

  ctx.body = {
    data: {
      msg: '添加成功',
    },
  };
});

// 获取文章[markdown]
router.get(urls.getArticleMarkdown, async ctx => {
  const articleID = ctx.query.id;
  const [errArticle, articleData]: any = await to(
    sql(`SELECT id,title,category,markdown,audio_src FROM article WHERE id = ${articleID}`),
  );

  if (errArticle) {
    return (ctx.body = SYSTEM_ERROR_MGS);
  }

  ctx.body = {
    data: {
      article: articleData.results[0],
    },
  };
});

// 获取文章[markdown]
router.post(urls.uploadFile, async ctx => {
  if (!(ctx.request.files && ctx.request.files.file)) {
    return (ctx.body = SYSTEM_ERROR_MGS);
  }
  const file = ctx.request.files.file;
  const ext = file.name.split('.').pop();

  const reader = fs.createReadStream(file.path);
  const reUrl = `/asstic/${ext === 'html' ? 'assets' : 'imgs'}/${uuidv4()}.${ext}`;
  const upStream = fs.createWriteStream(`${config.staticPath}${reUrl}`);
  reader.pipe(upStream);

  const [mvFileRspErr]: any = await to(fs.promises.rename(file.path, `${config.staticPath}${reUrl}`));

  if (mvFileRspErr) {
    return (ctx.body = ERROR_MGS(mvFileRspErr));
  }

  ctx.body = {
    data: {
      url: reUrl,
    },
  };
});

// 增加、更新文章[markdown]
router.post(urls.addBlog, async ctx => {
  const {id, markdown, category, title, audioSrc} = ctx.request.body;
  if (!(markdown && category && title)) {
    return (ctx.body = ERROR_MGS('请填写完文章'));
  }

  if (id) {
    const [updateErr]: any = await to(
      sql(
        `UPDATE article SET markdown = '${markdown.replace(/'/g, `\\'`).replace(/"/, `\\"`)}', title = '${title
          .replace(/'/g, `\\'`)
          .replace(/"/, `\\"`)}' , category = '${category
          .replace(/'/g, `\\'`)
          .replace(/"/, `\\"`)}', audio_src= '${audioSrc}' WHERE id = '${id}'`,
      ),
    );

    if (updateErr) {
      return (ctx.body = ERROR_MGS(updateErr));
    }

    return (ctx.body = {
      msg: '更新成功',
      data: {
        id,
      },
    });
  } else {
    const [insertErr, insertRes]: any = await await to(
      sql(
        `INSERT INTO article (markdown,title,category,release_date,audio_src) VALUES ('${markdown}','${title}','${category}','${formateTime(
          Date.now(),
          'YYYY-MM-DD HH:mm:SS',
        )}','${audioSrc}')`,
      ),
    );
    if (insertErr) {
      return (ctx.body = ERROR_MGS(insertErr));
    }

    return (ctx.body = {
      msg: '发布成功',
      data: {
        id: insertRes.results.insertId,
      },
    });
  }
});

// 获取文章列表
router.get(urls.getArticlesList, async ctx => {
  const [errCount, count]: any = await to(sql(`SELECT COUNT (*) as count FROM article`));
  if (errCount) {
    return (ctx.body = SYSTEM_ERROR_MGS);
  }
  const data: any = {
    count: count.results[0].count,
  };
  let {page, rowsPerPage} = ctx.query;
  page = parseInt(page);
  rowsPerPage = parseInt(rowsPerPage);
  if (page < 0 || rowsPerPage < 1) {
    return (ctx.body = ERROR_MGS('参数错误'));
  }
  const [errArticleList, articleList]: any = await to(
    sql(
      `SELECT id,title,category,release_date,visits FROM article ORDER BY id DESC LIMIT ${
        page * rowsPerPage
      },${rowsPerPage}`,
    ),
  );
  if (errArticleList) {
    return (ctx.body = SYSTEM_ERROR_MGS);
  }
  data.articleList = articleList.results;
  ctx.body = {
    data,
  };
});

// 删除文章
router.delete(urls.deleteArticle, async ctx => {
  const {id} = ctx.query;
  if (!id) {
    return (ctx.body = SYSTEM_ERROR_MGS);
  }

  const [deleteErr]: any = await to(sql(`DELETE FROM article WHERE id = '${id}'`));

  if (deleteErr) {
    return (ctx.body = SYSTEM_ERROR_MGS);
  }

  ctx.body = {
    msg: '删除成功',
  };
});

// 获取分类
router.get(urls.getCategory, async ctx => {
  const [deleteErr, categoryRsp]: any = await to(sql(`SELECT DISTINCT category FROM article`));

  if (deleteErr) {
    return (ctx.body = SYSTEM_ERROR_MGS);
  }

  const set = new Set();
  categoryRsp.results.map((item: {category: string}) => {
    item.category.split('-').map((category: string) => {
      set.add(category);
    });
  });
  ctx.body = {
    data: {
      category: Array.from(set),
    },
  };
});

export {router as adminRouter};
